Questo modulo ha lo scopo di introdurvi alle basi della programmazione ed alla sua applicazione al campo scientifico.
Nel corso di questo modulo useremo due linguaggi di programmazione di alto livello, python e matlab.
Oltre a questi linguaggi ne esistono moltissimi altri, tutti appropriati all'uso:
Vedremo anche nel corso delle lezioni vari concetti che vi torneranno utili qualsiasi sarà il linguaggio con cui deciderete di lavorare.
In particolare oggi inizieremo discutendo il controllo di versione.
Ma prima, che cosa sono i linguaggi di alto livello, e perché vale la pena usarli?
Il termine "linguaggio di alto livello" è una forma colloquiale, non definita in senso formale, ma sono presenti varie proprietà che li accumunano.
Lo scopo comune è rendere molto più semplice lo sviluppo di codice. Tutto il tempo che non passo a cercare di ricordare come inizializzare un puntatore, lo posso spendere a rendere le mie analisi più interessanti
vediamo un esempio che possa aiutare a capire che cosa intendo, usando il Python
import os
filenames = [filename for filename in os.listdir('.') if filename.endswith('.txt')]
for filename in filenames:
os.rename(filename, filename.replace('.txt', '.csv'))
Vedete che il codice, anche senza commenti, è chiaro e leggibile, ed esprimo dei concetti molto complicati in poche linee di codice
Oggi come oggi chi fa ricerca deve per forza scrivere del codice.
Ci viene insegnato a scrivere codice ma non a prendercene cura.
Un modo di dire comune nel campo dello sviluppo è:
Scrivi il tuo codice come se la prossima persona a doversene occupare fosse uno psicopatico che sa dove abiti.
Considerando il numero di progetti che lo scienziato medio deve seguire al giorno d'oggi, lo psicopatico in questione potreste essere voi!
Cosa è necessario per avere del codice salubre?
Durante questo corso cercheremo non solo di insegnarvi la programmazione di alto livello, ma anche come gestire i vostri progetti in modo da limitare il numero di momenti di terrore, disperazione e sconforto che avreste altrimenti.
Se pensate che stia scherzando, immaginate le seguenti situazioni:
Questi sono solo alcuni esempi, assolutamente visti capitare nella vita reale, fonti di stress facilmente evitabile.
Le procedure che vi insegneremo non possono ovviamente contrastare la sfortuna cieca, ma possono arginarne gli effetti nocivi ed evitare il disastro totale.
E sono tutte abbastanza semplici perché usarle non sia uno sforzo immane!
il concetto dietro questi esempi e questi strumenti è la corretta gestione dei metadata (dati a proposito dei dati).
Considerate un pezzo di programma come quello di prima. Il nome delle variabili è assolutamente arbitrario, e non influenza in nessun modo il risultato del programma, ma se cambiassi i nomi a caso il codice, seppure corretto, sarebbe incomprensibile, difficile da modificare e in poco tempo dimenticherei completamente il suo scopo d'essere.
Nel codice di solito si usano nomi coerenti e commenti, ma c'è molto altro di cui possiamo tenere traccia se ne siamo consci.
Avete mai avuto diverse copie di un file, chiamate doc_v1, doc_v2 e così via?
Bene, quello è un controllo di versione manuale. Grazie al computer possiamo fare di meglio.
Possiamo tenere traccia di tutto quello che succede, tornare indietro ad un momento qualsiasi, vedere le differenze fra due versioni successive ed anche tenere "universi paralleli" di versioni alternative.
I programmi che permettono di farlo sono i Sistemi di Controllo di Versione.
Questi sono poi affiancati da sistemi di Management del Codice Sorgente, che oltre a tenere traccia della versione permettono anche di tracciare i bug e la documentazione.
Fossil è una semplice soluzione integrata che vi fornisce tutto questo in un unico pacchetto.
È già estremamente utile per lavorare da soli, e permette di usare lo stesso strumento per collaborare, coordinando il lavoro di varie persone che lavorano allo stesso progetto, online ed offline.
Le collaborazioni avvengono tramite un server centrale che fa da punto di scambio.
Potete anche ospitarlo su di un vostro computer, il server è lo stesso programma che avete già scaricato.
Ogni modifica che farete sarà automaticamente registrata sul server in automatico, e passata agli altri quando si collegheranno.
cit:
se vale la pena di essere fatto, vale la pena di essere messo sotto controllo di versione
si può scaricare dal suo sito web: Fossil-SCM.
È un programma free ed open source, cross-platform e contenuto in un unico file, quindi è molto facile da spostare in giro.
Il vostro repository è contenuto in un unico file, un database che contiene tutte le informazioni rilevanti (new).
Fare il backup dell'intero repository con TUTTE le informazioni è semplicemente copiare il file in giro. basta tenerlo nella cartella di sincronizzazione di dropbox ed il problema è risolto.
Potete estrarne l'ultima versione in una cartella (open), modificarla e, quando siete soddisfatti del risultato, inserirla come una versione successiva (commit).
Potete usare il controllo di versione per qualsiasi file text-based che volete, non soltanto il codice.
Ad esempio tenere la propria tesi ed il testo dei propri articoli sotto controllo di versione è generalmente una buona idea.
Ogni volta che vi allontanate dall'usare file di teste, perdete tutta la potenza di questi sistemi di controllo, ed è un vantaggio insostituibile!
!fossil init mytestrepo.fossil
project-id: 08090f56228b95bd9372d6d15fc632dcaaa91edb server-id: 0f917f69c95b135b5e526bc91e8028ce98b09083 admin-user: enrico (initial password is "b16604")
%ls
mytestrepo.fossil
%mkdir -p working_directory
%cd working_directory
%pwd
/home/enrico/lavoro/fossilexample/working_directory
'/home/enrico/lavoro/fossilexample/working_directory'
!fossil open ../mytestrepo.fossil
project-name: <unnamed> repository: /home/enrico/lavoro/fossilexample/working_directory/../mytestrepo.fossil local-root: /home/enrico/lavoro/fossilexample/working_directory/ config-db: /home/enrico/.fossil project-code: 08090f56228b95bd9372d6d15fc632dcaaa91edb checkout: e17a3d4a58fef68da694289aa32334d82bde5234 2017-02-27 20:27:38 UTC tags: trunk comment: initial empty check-in (user: enrico) check-ins: 1
%%writefile test.txt
This is going to be my documentation
Writing test.txt
!fossil status
repository: /home/enrico/lavoro/fossilexample/working_directory/../mytestrepo.fossil local-root: /home/enrico/lavoro/fossilexample/working_directory/ config-db: /home/enrico/.fossil checkout: e17a3d4a58fef68da694289aa32334d82bde5234 2017-02-27 20:27:38 UTC tags: trunk comment: initial empty check-in (user: enrico)
!fossil extra
test.txt
!fossil add test.txt
ADDED test.txt
!fossil status
repository: /home/enrico/lavoro/fossilexample/working_directory/../mytestrepo.fossil local-root: /home/enrico/lavoro/fossilexample/working_directory/ config-db: /home/enrico/.fossil checkout: e17a3d4a58fef68da694289aa32334d82bde5234 2017-02-27 20:27:38 UTC tags: trunk comment: initial empty check-in (user: enrico) ADDED test.txt
!fossil commit -m "il primo file di un grande progetto!"
New_Version: 2dab9716e96fab6bcf87e8d8e17b3a672bfea4eb
!fossil status
repository: /home/enrico/lavoro/fossilexample/working_directory/../mytestrepo.fossil local-root: /home/enrico/lavoro/fossilexample/working_directory/ config-db: /home/enrico/.fossil checkout: 2dab9716e96fab6bcf87e8d8e17b3a672bfea4eb 2017-02-27 20:34:25 UTC parent: e17a3d4a58fef68da694289aa32334d82bde5234 2017-02-27 20:27:38 UTC tags: trunk comment: il primo file di un grande progetto! (user: enrico)
a questo punto potete vedere cosa succere lanciando il comando
fossil ui
%%writefile test.txt
This is going to be my documentation
I'm adding more lines: the more, the merrier!
Overwriting test.txt
!fossil status
repository: /home/enrico/lavoro/fossilexample/working_directory/../mytestrepo.fossil local-root: /home/enrico/lavoro/fossilexample/working_directory/ config-db: /home/enrico/.fossil checkout: 2dab9716e96fab6bcf87e8d8e17b3a672bfea4eb 2017-02-27 20:34:25 UTC parent: e17a3d4a58fef68da694289aa32334d82bde5234 2017-02-27 20:27:38 UTC tags: trunk comment: il primo file di un grande progetto! (user: enrico) EDITED test.txt
!fossil diff test.txt
Index: test.txt ================================================================== --- test.txt +++ test.txt @@ -1,1 +1,2 @@ This is going to be my documentation +I'm adding more lines: the more, the merrier!
!fossil commit -m "espansa la documentazione"
New_Version: 1856bb82f3515646637061c6e062c117fc646192
mi sono accorto di aver fatto un errore!
come posso rimediare?
Per prima cosa, lascio traccia della decisione: apro un ticket.
!fossil help revert
Usage: fossil revert ?-r REVISION? ?FILE ...? Revert to the current repository version of FILE, or to the version associated with baseline REVISION if the -r flag appears. If FILE was part of a rename operation, both the original file and the renamed file are reverted. Revert all files if no file name is provided. If a file is reverted accidently, it can be restored using the "fossil undo" command. Options: -r REVISION revert given FILE(s) back to given REVISION See also: redo, undo, update
!fossil revert -r 2dab9716e9 test.txt
REVERT test.txt "fossil undo" is available to undo changes to the working checkout.
!fossil status
repository: /home/enrico/lavoro/fossilexample/working_directory/../mytestrepo.fossil local-root: /home/enrico/lavoro/fossilexample/working_directory/ config-db: /home/enrico/.fossil checkout: 1856bb82f3515646637061c6e062c117fc646192 2017-02-27 20:42:51 UTC parent: 2dab9716e96fab6bcf87e8d8e17b3a672bfea4eb 2017-02-27 20:34:25 UTC tags: trunk comment: espansa la documentazione (user: enrico) EDITED test.txt
!fossil diff test.txt
Index: test.txt ================================================================== --- test.txt +++ test.txt @@ -1,2 +1,1 @@ This is going to be my documentation -I'm adding more lines: the more, the merrier!
!fossil commit -m "riportato l'ordine nel repository!"
New_Version: 488479276df60e9fd055d5dbe07ee6c37b30beb3
ora non mi rimane che chiudere il ticket e continuare il mio lavoro
una funzionalità molto potente per il controllo di versione è la possibilità di fare branching.
Questo significa che nel mio database esistono nello stesso momento due versioni diverse dello stesso progetto, e posso passare da un all'altra senza problemi.
Un grosso vantaggio del modello di DVCS di fossil è che posso usare diverse cartelle per diversi branch, ed avere il tutto sincronizzato!
avete appena raggiunto un risultato pubblicabile con le vostre analisi, e volete prepararvi per pubblicarle.
Questo significa che non altererete più il codice in modo sostanziale (volete mantenere l'integrità dei risultati), ma magari aggiusterete i grafici ed i report.
Allo stesso momento, i vostri collaboratori vi chiedono di fare delle modifiche piuttosto importanti del codice. Come potete fare?
Usando due diverse branch siete in grado di dividere il lavoro senza fare confusione, ma mantenendo tutto sempre sotto controllo (e con la possibilità di far passare i risultati da un branch all'altro con revert).
!fossil help checkout
Usage: fossil checkout ?VERSION | --latest? ?OPTIONS? or: fossil co ?VERSION | --latest? ?OPTIONS? Check out a version specified on the command-line. This command will abort if there are edited files in the current checkout unless the --force option appears on the command-line. The --keep option leaves files on disk unchanged, except the manifest and manifest.uuid files. The --latest flag can be used in place of VERSION to checkout the latest version in the repository. Options: --force Ignore edited files in the current checkout --keep Only update the manifest and manifest.uuid files --force-missing Force checkout even if content is missing See also: update
per comodità faremo il cambio di branch nella stessa directory, ma in generale creeremmo una seconda directory, apriremmo il repository e faremmo il checkout della versione che ci interessa.
In questo caso, ritorniamo allo stato iniziale del repository.
!fossil checkout e17a3d4a58
il repository è vuoto come l'abbiamo lasciato due commit fa.
ls
%%writefile test.txt
this is an alternative history
Writing test.txt
!fossil add test.txt
ADDED test.txt
!fossil commit -m "nuova storia"
would fork. "update" first or use --allow-fork.
!fossil commit --allow-fork -m "nuova storia"
New_Version: 5d56786fcd0396b860365fe6ea6f01c8186818cb **** warning: a fork has occurred *****
notate che viene registrato anche il cambiamento di nome del branch!
Un'altra operazione molto comune è rinominare o eliminare un file.
Un comportamento curioso di fossil è che registra il cambiamento ma non lo attua: dovete esplicitamente rinominare il file dalla linea di comando
!fossil mv test.txt test2.txt
RENAME test.txt test2.txt
!ls
test.txt
!mv test.txt test2.txt
!fossil status
repository: /home/enrico/lavoro/fossilexample/working_directory/../mytestrepo.fossil local-root: /home/enrico/lavoro/fossilexample/working_directory/ config-db: /home/enrico/.fossil checkout: 5d56786fcd0396b860365fe6ea6f01c8186818cb 2017-02-27 21:23:41 UTC parent: e17a3d4a58fef68da694289aa32334d82bde5234 2017-02-27 20:27:38 UTC tags: experiment comment: nuova storia (user: enrico) RENAMED test2.txt
!fossil commit -m "cambiato il nome del file"
New_Version: 5728ff85e15a79f162bb955aa4a0638967aebe0c
!rm test2.txt
!fossil rm test2.txt
DELETED test2.txt
%%writefile test3.txt
crazy experiments!
Writing test3.txt
!fossil add test3.txt
ADDED test3.txt
!fossil commit -m "ultimo commit del branch sperimentale"
New_Version: 47cc19ae1f35b62a524f2b5ddc4e45d96d6b2bc7
Ora, visto che ci piace renderci la vita complicata, vogliamo unire i due branch.
Questo può servire quando stiamo facendo delle modifiche sperimentali ad una parte della nostra analisi e non vogliamo includerlo fintanto che non siamo sicuri che stia funzionando correttamente.
Per fare questo dobbiamo usare il comando merge, ma prima dobbiamo metterci nella linea principale che vogliamo mantenere (visto che l'altra poi sparirà) con un checkout.
Questo risulta molto più facile se avete due cartelle separate. Se state usando la stessa, controllate due volte prima di fare il checkout!
!fossil checkout 488479276d
test.txt
!fossil merge 47cc19ae1f --dry-run
ADDED test3.txt REMINDER: this was a dry run - no files were actually changed.
!fossil merge 47cc19ae1f
ADDED test3.txt "fossil undo" is available to undo changes to the working checkout.
!fossil status
repository: /home/enrico/lavoro/fossilexample/working_directory/../mytestrepo.fossil local-root: /home/enrico/lavoro/fossilexample/working_directory/ config-db: /home/enrico/.fossil checkout: 488479276df60e9fd055d5dbe07ee6c37b30beb3 2017-02-27 20:56:16 UTC parent: 1856bb82f3515646637061c6e062c117fc646192 2017-02-27 20:42:51 UTC tags: trunk comment: riportato l'ordine nel repository! (user: enrico) ADDED_BY_MERGE test3.txt MERGED_WITH 47cc19ae1f35b62a524f2b5ddc4e45d96d6b2bc7
!fossil commit -m "le due storie sono finalmente unite!"
New_Version: cb5317076a540e3c4799ff184d509de665d47ddb
Il file che abbiamo modificato all'inizio, test.txt, dava problemi per il merge perchè creato indipendentemente nei due branch. L'unica soluzione che ho trovato è stata gestire il merge a mano, in pratica creare un nuovo file da zero ed eventualmente riempirlo con il contenuto del vecchio.